package com.huaxin.dss2.data.dao.base;

import com.google.common.collect.Lists;
import com.huaxin.dss2.data.bean.DataInfo;
import com.huaxin.dss2.data.bean.DataValue;
import com.huaxin.dss2.data.bean.DssBox;
import com.huaxin.dss2.data.bean.properties.HxDssProperties;
import com.huaxin.dss2.data.exception.jdbc.DataSourceNotFoundException;
import com.huaxin.dss2.message.exception.SaveRealDataException;
import java.sql.SQLException;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

/**
 * @author luqing
 * @date 2018/6/27 14:50
 */
@Component
@Slf4j
public abstract class BaseDataDao {


    protected JdbcTemplate jdbcTemplate;
    protected HxDssProperties hxDssProperties;

    @Autowired
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Autowired
    public void setHxDssProperties(HxDssProperties hxDssProperties) {
        this.hxDssProperties = hxDssProperties;
    }

    /**
     * 初始化方法
     */
    public abstract void init();

    /**
     * 数据保存抽象方法
     * @param stationCode mysql版本需要通过stationCode进行分库 oracle和hbase版本不需要
     * @param saveList 需要保存的数据
     * @param dataDate 存入时间
     * @throws Exception 抛出异常，包括但不限于一下三种
     * @throws DataSourceNotFoundException 数据源找不到异常
     * @throws SaveRealDataException 保存真实数据异常
     * @throws SQLException 数据库异常
     */
    public abstract void save(String stationCode,final List<DataValue> saveList, Date dataDate)
        throws Exception;


    @Cacheable(value = {"stationDataInfoMap"},key = "#stationId")
    public Map<String,DataInfo> findDataInfoMap(String stationId) {
        List<DataInfo> dataInfoList = findDataInfoList(stationId);
        Map<String,DataInfo> dataInfoMap = new HashMap<>(dataInfoList.size());
        for(DataInfo dataInfo : dataInfoList){
            dataInfoMap.put(dataInfo.getFullDataCode(),dataInfo);
        }
        return Collections.unmodifiableMap(dataInfoMap);
    }


    /**
     * 刷新站点缓存,并删除对应的数据库数据
     * @param stationId 站点Code
     */
    @CacheEvict(value = {"stationDataInfoMap"},key = "#stationId")
    public void refreshDataInfo(String stationId,Integer type){
        log.info("{}站点状态变化,刷新缓存",stationId);
        Boolean b = deleteChangeBox(stationId,type);
        if (!b){
            log.error("{}站点缓存数据删除失败",stationId);
        }
    }

    /**
     * 获取所有站点
     * 使用配置sql方式进行获取stationCodeList
     * sql : select stationCode from station_table [where stationType = ? (1为站，0为厂)]
     * @return 返回所有站点
     */
    public List<String> findSmallStationCodes(){
//        String sql = "select stationCode from v_station where stationType =1";
//        String sql = "select " + stationTableStationCodeColumnName + " from "+ stationTable;
//        String sql = PropertiesUtil.getSql("stationListSql");
        String sql = hxDssProperties.getSql().getStationListSql();
        return jdbcTemplate.queryForList(sql, String.class);
    }

    /**
     * 获取站点所有指标集合
     * @param stationCode  站点Code
     * 使用配置sql方式进行获取DataInfoList
     * sql : select * from dataInfo_table where stationCode = ? (stationCode)
     * @return 站点的相关指标
     */
    public List<DataInfo> findDataInfoList(String stationCode) {
//        String sql = "select * from " + dataInfoTable + " where " + dataInfoTableStationCodeColumnName + "=?";
//        String sql = PropertiesUtil.getSql("dataInfoAllListSql");
        String sql = hxDssProperties.getSql().getDataInfoAllListSql();
        return jdbcTemplate.query(sql,new BeanPropertyRowMapper<>(DataInfo.class),stationCode);
    }

    /**
     * 统计站点状态变更的数据
     * @return 统计结果
     */
    public List<DssBox> findChangeBox() {
        try {
            String sql = "select * from c_dss_box";
            synchronized (this){
                return jdbcTemplate.query(sql,new BeanPropertyRowMapper<>(DssBox.class));
            }

        } catch (DataAccessException e) {
            log.info("统计改变站点发生异常",e);
            return Lists.newArrayList();
        }
    }

    /**
     * 删除c_dss_box表中的数据
     * @param stationCode 站点Code
     * @return 删除结果
     */
    private Boolean deleteChangeBox(String stationCode,Integer type){
        try {
            String sql = "delete from c_dss_box where stationCode = ? AND type = ?";
            jdbcTemplate.update(sql,stationCode,type);
            return true;
        } catch (DataAccessException e) {
            log.error("删除失败",e);
            return false;
        }
    }

    /**
     * 获取DataInfo
     * @param stationCode stationCode
     * @param dataItemId dataItemId
     * @param dataCode dataCode
     * @return dataInfo
     * 使用配置sql方式进行获取DataInfoList
     * sql : select * from dataInfo_table where stationCode=? (stationCode) and dataItemId= ? (dataItemId) and dataCode= ? (dataCode)
     */
    public DataInfo findDataInfo(String stationCode,Long dataItemId,String dataCode) {

//        String sql = "select * from " + dataInfoTable + " where " + dataInfoTableStationCodeColumnName +" =? and dataItemId=? and dataCode=?";
//        PropertiesUtil.getSql("dataInfoOneSql");
        String sql = hxDssProperties.getSql().getDataInfoOneSql();

        List<DataInfo> dataInfos = jdbcTemplate.query(sql,new BeanPropertyRowMapper<>(DataInfo.class),stationCode,dataItemId,dataCode);
        if(dataInfos.size()>0) {
            return dataInfos.get(0);
        }
        return null;
    }
}
